﻿namespace Pub.Class
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.IO;
    using System.Linq;
    using System.Reflection;

    public static class Dumper
    {
        public static void Dump(object value, string name, TextWriter writer)
        {
            if (name.IsNullEmpty())
            {
                throw new ArgumentNullException("name");
            }
            if (writer.IsNull())
            {
                throw new ArgumentNullException("writer");
            }
            Dictionary<object, int> lookup = new Dictionary<object, int>();
            InternalDump(0, name, value, writer, lookup, true);
        }

        private static void InternalDump(int indentationLevel, string name, object value, TextWriter writer, Dictionary<object, int> lookup, bool recursiveDump)
        {
            string str = new string(' ', indentationLevel * 3);
            if (value.IsNull())
            {
                writer.WriteLine("{0}{1} = <null>", str, name);
            }
            else
            {
                Type type = value.GetType();
                string str2 = string.Empty;
                string str3 = string.Empty;
                if (!type.IsValueType)
                {
                    int num;
                    if (lookup.TryGetValue(value, out num))
                    {
                        str2 = string.Format(CultureInfo.InvariantCulture, " (see #{0})", new object[] { num });
                    }
                    else
                    {
                        num = lookup.Count + 1;
                        lookup[value] = num;
                        str3 = string.Format(CultureInfo.InvariantCulture, "#{0}: ", new object[] { num });
                    }
                }
                bool flag = value is string;
                string fullName = value.GetType().FullName;
                string str5 = value.ToString();
                Exception exception = value as Exception;
                if (exception.IsNotNull())
                {
                    str5 = exception.GetType().Name + ": " + exception.Message;
                }
                if (str5 == fullName)
                {
                    str5 = string.Empty;
                }
                else
                {
                    str5 = str5.Replace("\t", @"\t").Replace("\n", @"\n").Replace("\r", @"\r");
                    int length = str5.Length;
                    if (length > 80)
                    {
                        str5 = str5.Substring(0, 80);
                    }
                    if (flag)
                    {
                        str5 = string.Format(CultureInfo.InvariantCulture, "\"{0}\"", new object[] { str5 });
                    }
                    if (length > 80)
                    {
                        object obj4 = str5;
                        str5 = string.Concat(new object[] { obj4, " (+", length - 80, " chars)" });
                    }
                    str5 = " = " + str5;
                }
                writer.WriteLine("{0}{1}{2}{3} [{4}]{5}", new object[] { str, str3, name, str5, value.GetType(), str2 });
                if ((((str2.Length <= 0) && !flag) && (!type.IsValueType || (type.FullName != ("System." + type.Name)))) && recursiveDump)
                {
                    PropertyInfo[] infoArray = (from property in type.GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)
                        where (property.GetIndexParameters().Length == 0) && property.CanRead
                        select property).ToArray<PropertyInfo>();
                    FieldInfo[] infoArray2 = type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance).ToArray<FieldInfo>();
                    if ((infoArray.Length != 0) || (infoArray2.Length != 0))
                    {
                        writer.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0}{{", new object[] { str }));
                        if (infoArray.Length > 0)
                        {
                            writer.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0}   properties {{", new object[] { str }));
                            foreach (PropertyInfo info in infoArray)
                            {
                                try
                                {
                                    object obj2 = info.GetValue(value, null);
                                    InternalDump(indentationLevel + 2, info.Name, obj2, writer, lookup, true);
                                }
                                catch (TargetInvocationException exception2)
                                {
                                    InternalDump(indentationLevel + 2, info.Name, exception2, writer, lookup, false);
                                }
                            }
                            writer.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0}   }}", new object[] { str }));
                        }
                        if (infoArray2.Length > 0)
                        {
                            writer.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0}   fields {{", new object[] { str }));
                            foreach (FieldInfo info2 in infoArray2)
                            {
                                try
                                {
                                    object obj3 = info2.GetValue(value);
                                    InternalDump(indentationLevel + 2, info2.Name, obj3, writer, lookup, true);
                                }
                                catch (TargetInvocationException exception3)
                                {
                                    InternalDump(indentationLevel + 2, info2.Name, exception3, writer, lookup, false);
                                }
                            }
                            writer.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0}   }}", new object[] { str }));
                        }
                        writer.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0}}}", new object[] { str }));
                    }
                }
            }
        }
    }
}

